package com.bitin.adorn.core.security.expression;

import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.expression.MethodBasedEvaluationContext;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.parameters.DefaultSecurityParameterNameDiscoverer;

import java.lang.reflect.Method;

/**
 * @author Mr.Lu
 * @since 2024/12/24 17:13
 */
public class Auth2MethodSecurityEvaluationContext extends MethodBasedEvaluationContext {

    public Auth2MethodSecurityEvaluationContext(Authentication authentication, MethodInvocation invocation) {
        this((Authentication) authentication, invocation, new DefaultSecurityParameterNameDiscoverer());
    }

    public Auth2MethodSecurityEvaluationContext(Authentication authentication, MethodInvocation invocation, ParameterNameDiscoverer parameterNameDiscoverer) {
        super(invocation.getThis(), getSpecificMethod(invocation), invocation.getArguments(), parameterNameDiscoverer);
    }

    public Auth2MethodSecurityEvaluationContext(MethodSecurityExpressionOperations securityExpressionOperations, MethodInvocation invocation, ParameterNameDiscoverer parameterNameDiscoverer) {
        super(securityExpressionOperations, getSpecificMethod(invocation), invocation.getArguments(), parameterNameDiscoverer);
    }

    private static Method getSpecificMethod(MethodInvocation invocation) {
        return AopUtils.getMostSpecificMethod(invocation.getMethod(), AopProxyUtils.ultimateTargetClass(invocation.getThis()));
    }
}
